import {ArrayMethods} from '../observer/arr.js'

export function observer(data) {
    //console.log('数据劫持:',data)

    // 判断
    if (typeof data != 'object' || data == null) {
        return data
    }

    // 是对象 通过一个类来劫持
    return new Observer(data)
}

class Observer {
    constructor(value) {
        // 判断 数据是数组还是对象
        if (Array.isArray((value))) {
            value.__proto__ = ArrayMethods
            //console.log('数组', value)
        } else {
            // console.log('对象', value)
            this.walk(value) // 进来就遍历
        }

    }

    walk(data) {
        let keys = Object.keys(data)
        for (let i = 0; i < keys.length; i++) {
            let key = keys[i];
            let value = data[key];
            defineReactive(data, key, value)
        }
    }
}


// 针对对象中的属性进行劫持
function defineReactive(data, key, value) {
    observer(value) // 深度代理
    Object.defineProperty(data, key, {
        get() {
            //console.log('获取')
            return value
        },
        set(newVal) {
            if (newVal === value) return value
            observer(data) // 如果值是对象就递归
            value = newVal
        }
    })
}

//  第一种：对象的劫持
// 1、 通过 Object.defindeProperty方法   （缺点: 只能针对对象中的一个属性进行劫持）
// 2、 遍历{a:1,b:2,Obj:{}}
// 3、 递归  get()  set()

// 第二种：数组的劫持：  如{ list:[1,2,3,4] }   arr:[{a:1}]
// 通过函数劫持（方法函数劫持）
// 方式：重写数组方法
// 步骤：见arr.js
